﻿using System;

namespace Fuse8.DomainFramework.Common
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="valueType"></param>
    /// <param name="val"></param>
    /// <returns></returns>
    public delegate object ConvertToType(string valueType, string val);

    /// <summary>
    /// 
    /// </summary>
    public static class TypeInterpreter
    {   
        #region Interpreter factory

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="val"></param>
        /// <param name="dlg"></param>
        /// <returns></returns>
        public static object GetValue<T>(T val, ConvertToType dlg)
        {
            return GetValue(GetTypeName(typeof(T)), val.ToString(), dlg);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="valueType"></param>
        /// <param name="val"></param>
        /// <param name="dlg"></param>
        /// <returns></returns>
        public static object GetValue(string valueType, string val, ConvertToType dlg)
        {
            object result = null;

            if (valueType == GetTypeName(typeof(string)))
            {
                result = val;
            }
            else if (valueType == GetTypeName(typeof(int)))
            {
                result = GetInt32(val);
            }
            else if (valueType == GetTypeName(typeof(float)))
            {
                result = GetSingle(val);
            }
            else if (valueType == GetTypeName(typeof(double)))
            {
                result = GetDouble(val);
            }
            else if (valueType == GetTypeName(typeof(decimal)))
            {
                result = GetDecimal(val);
            }
            else if (valueType == GetTypeName(typeof(bool)))
            {
                result = GetBoolean(val);
            }
            else if (valueType == GetTypeName(typeof(DateTime)))
            {
                result = GetDateTime(val);
            }
            else
            {
                if (dlg != null)
                {
                    result = dlg.Invoke(valueType, val);
                }
            }

            return result;
        }

        /// <summary>
        /// Get type name in specific format [FullName, AssemblyName]
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetTypeName(Type type)
        {
            return string.Format("{0}, {1}", type.FullName, type.Assembly.GetName().Name);
        }

        #endregion

        #region Convert methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static int GetInt32(string val)
        {
            int result;

            if (!int.TryParse(val, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static float GetSingle(string val)
        {
            float result;

            if (!float.TryParse(val, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static double GetDouble(string val)
        {
            double result;

            if (!double.TryParse(val, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static decimal GetDecimal(string val)
        {
            decimal result;

            if (!decimal.TryParse(val, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool GetBoolean(string val)
        {
            bool result;

            if (!bool.TryParse(val, out result))
            {
                result = false;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static DateTime GetDateTime(string val)
        {
            DateTime result;

            if (!DateTime.TryParse(val, out result))
            {
                result = DateTime.MinValue;
            }

            return result;
        }

        #endregion


    }
}
